﻿/**
  * @file:     run_shell_cmd.h
  * @author    陈猛
  * @em:       chen-meng@example.com
  * @date:     2019年09月25日 星期三 10时53分31秒
  * @details:  用来同步运行系统shell命令等
 ************************************************************************/
#ifndef _RUN_SHELL_CMD_H_
#define _RUN_SHELL_CMD_H_

#include "run_cmd_base.h"
#include "list_table.h"

/**
 * @brief The RunShellCmd class
 *  简单的类似与系统API system函数，但是不使用sh -c 运行，不等传递环境变量，直接使用
 *  exec族函数，运行新进程
 */
class RunShellCmd : public RunCmdBase
{
public:
    /**
     * @brief RunShellCmd
     * @param cmd [in] 执行程序名字
     * @note 传入命令的名字，不许附带参数; 是否需要获得执行命令的返回结果
     */
    RunShellCmd(const char *cmd);

    ~RunShellCmd();

    /* 命令执行 */
    int exec()
    {
        return system();
    }
    /**
     * @brief system
     * @return 执行命令的返回的状态，是一个unsigned char类型的值     
     *  返回0表示执行正确，非0表示执行失败，这个linux系统中的默认规则
     *  例如：int main() { return -12; }
     *       测试程序main函数 return -12, 此处就 会返回244
     *       测试程序main函数 return 10, 此处就  会返回10
     *       测试程序main函数 return 300, 此处就 会返回44
     *       因此得出程序返回值的范围是0～255
     * @note 所以要判断执行的程序状态，就只有0和非0,作 为结果，其中0为成功，非0为，执行错误
     */
    int system();
};

/**
 * @brief The RunPipeCmd class
 *  运行命令，但是打开新的管道，用于接收程序的运行结构
 */
class RunPipeCmd : public RunCmdBase
{
public:
    enum RunType
    {
        READ, WRITE,
        RUNMAX,
    };
    RunPipeCmd(const char *cmdName);
    ~RunPipeCmd();

    /**
     * @brief exec
     * @param type 传递值类型，标志当前命令是要读数据和是写数据
     * @return 返回管道文件秒数符，错误返回-1
     */
    int exec(int type = READ);

    //! 杀死当前执行的命令
    void kill();

    int readData(char *buff, int len, int msec);
    int writeData(const char *buff, int len, int msec);

    int readn(char *buff, int len);
    int writen(char *buff, int len);


private:
    pid_t m_pid;
    int   m_fd;
};

#endif // _RUN_SHELL_CMD_H_

